package com.xxcxcxcx.jobsystem.common.command;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.arguments.DoubleArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.xxcxcxcx.jobsystem.Main;
import com.xxcxcxcx.jobsystem.PlayerSaveData;
import com.xxcxcxcx.jobsystem.common.command.argumets.JobArgument;
import com.xxcxcxcx.jobsystem.common.command.argumets.JobParameterArgument;
import com.xxcxcxcx.jobsystem.common.JobsClass;
import com.xxcxcxcx.jobsystem.common.capability.JobCapability;
import com.xxcxcxcx.jobsystem.common.capability.JobCapabilityProvider;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.common.util.LazyOptional;

public class LevelCommand {
    public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
        final LiteralArgumentBuilder<CommandSourceStack> get, set, all;
        //命令格式: job get [player] [job]
        get = Commands.literal("get")
                .requires(commandSource -> commandSource.hasPermission(0))
                .executes(context -> GetAllJob(context.getSource()))
                .then(
                    Commands.argument("targets", EntityArgument.player())
                        .requires(commandSource -> commandSource.hasPermission(4))
                        .executes(context -> GetPlayerAllJob(context.getSource(), EntityArgument.getPlayer(context, "targets")))
                        .then(
                            Commands.argument("job", JobArgument.job())
                                .executes(context2 -> GetJobMessageAll(JobArgument.getJob(context2, "job"), EntityArgument.getPlayer(context2, "targets"))).then(Commands.argument("jobParameter", JobParameterArgument.jobParameter()).executes(context3 -> GetJobMessage(JobArgument.getJob(context3, "job"), JobParameterArgument.getJobParameter(context3, "jobParameter"), EntityArgument.getPlayer(context3, "targets"))))
                        )
                );
        //命令格式: job set <player> <job> <parameter> <value>
        set = Commands.literal("set")
                .requires(commandSource -> commandSource.hasPermission(4))
                .then(
                    Commands.argument("targets", EntityArgument.player())
                        .then(
                            Commands.argument("job", JobArgument.job())
                                .then(
                                    Commands.argument("jobParameter", JobParameterArgument.jobParameter())
                                        .then(
                                            Commands.argument("value", DoubleArgumentType.doubleArg())
                                                .executes(context -> SetJobValue(JobArgument.getJob(context, "job"), JobParameterArgument.getJobParameter(context, "jobParameter"), DoubleArgumentType.getDouble(context, "value"), EntityArgument.getPlayer(context, "targets")))
                                        )
                                )
                        )
                );
        //命令格式: job gainexperience <bool> [player]
        all = Commands.literal(Main.MOD_ID)
                .then(
                    Commands.literal("gainexperience")
                        .requires(commandSource -> commandSource.hasPermission(0))
                        .executes(context -> GetRead(context.getSource()))
                        .then(
                            Commands.argument("bool", BoolArgumentType.bool())
                                .executes(context -> SetRead(BoolArgumentType.getBool(context, "bool"), context.getSource()))
                                .then(
                                    Commands.argument("targets", EntityArgument.player())
                                        .requires(commandSource -> commandSource.hasPermission(4))
                                        .executes(context -> SetRead(BoolArgumentType.getBool(context, "bool"), EntityArgument.getPlayer(context, "targets")))
                                )
                        )
                ).then(get).then(set);
        final LiteralCommandNode<CommandSourceStack> cmd = dispatcher.register(all);
        dispatcher.register(Commands.literal("job").redirect(cmd));
    }

    public static int GetPlayerAllJob(CommandSourceStack context, Player players) {
        for(String job : JobsClass.Jobs) {
            GetJobMessageAll(job, players);
        }
        return 0;
    }

    public static int GetAllJob(Player player) {
        for(String job : JobsClass.Jobs) {
            GetJobMessageAll(job, player);
        }

        return 0;
    }

    public static int GetAllJob(CommandSourceStack context) {
        if(context.getEntity() instanceof ServerPlayer) {
            return GetAllJob((ServerPlayer) context.getEntity());
        }
        return 0;
    }

    public static int GetJobMessageAll(String job, Player player) {
        JobCapabilityProvider.getPlayerData(player).ifPresent(playerSaveData -> {
            OutMessage(player);
            player.sendMessage((new TranslatableComponent("jobsystem.commands.jobmessageall", new TranslatableComponent("jobsystem.job." + job).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}))), player.getUUID());
            OutMessage(player, job, JobParameterArgument.LEVEL);
            OutMessage(player, job, JobParameterArgument.EXPERIENCE);
            player.sendMessage((new TranslatableComponent("jobsystem.commands.maxexperience", new TranslatableComponent(playerSaveData.getLevel(job) >= 10 ? "无限大" : Integer.toString(JobsClass.xp[playerSaveData.getLevel(job)])).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}))), player.getUUID());
            OutMessage(player, job, JobParameterArgument.COEFFICIENT);
            OutMessage(player);
        });

        return 0;
    }

    public static int SetJobValue(String job, String kind, double value, ServerPlayer player) {
        JobCapabilityProvider.getPlayerData(player).ifPresent(playerSaveData -> {
            player.sendMessage(new TextComponent(job + " " + kind + " " + value), player.getUUID());
            switch(kind) {
                case JobParameterArgument.LEVEL:
                    playerSaveData.setLevel(job, (int) value);
                    player.sendMessage((new TranslatableComponent("jobsystem.commands.set" + kind, new TranslatableComponent("jobsystem.job." + job).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}), new TranslatableComponent(Integer.toString((int) value)).withStyle(new ChatFormatting[] {ChatFormatting.RED}))), player.getUUID());
                case JobParameterArgument.EXPERIENCE:
                    playerSaveData.setExperience(job, value);
                    player.sendMessage((new TranslatableComponent("jobsystem.commands.set" + kind, new TranslatableComponent("jobsystem.job." + job).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}), new TranslatableComponent(Double.toString(value)).withStyle(new ChatFormatting[] {ChatFormatting.RED}))), player.getUUID());
                    break;
                case JobParameterArgument.COEFFICIENT:
                    playerSaveData.setCoefficient(job, value);
                    player.sendMessage((new TranslatableComponent("jobsystem.commands.set" + kind, new TranslatableComponent("jobsystem.job." + job).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}), new TranslatableComponent(Double.toString(value)).withStyle(new ChatFormatting[] {ChatFormatting.RED}))), player.getUUID());
                    break;
            }
        });

        return 0;
    }

    public static int GetJobMessage(String job, String kind, Player player) {
        JobCapabilityProvider.getPlayerData(player).ifPresent(playerSaveData -> {
            OutMessage(player, job, kind);
            if(kind == "experience") {
                player.sendMessage((new TranslatableComponent("jobsystem.commands.maxexperience", new TranslatableComponent(playerSaveData.getLevel(job) >= 10 ? "无限大" : Integer.toString(JobsClass.xp[playerSaveData.getLevel(job)])).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}))), player.getUUID());
            }
        });

        return 0;
    }

    public static void OutMessage(Player player, String job, String kind) {
        player.sendMessage((new TranslatableComponent("jobsystem.commands.get" + kind, new TranslatableComponent("jobsystem.job." + job).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}), new TranslatableComponent(GetAns(player, job, kind)).withStyle(new ChatFormatting[] {ChatFormatting.RED}))), player.getUUID());
    }

    public static void OutMessage(Player player) {
        player.sendMessage((new TranslatableComponent("jobsystem.commands.separate")), player.getUUID());
    }

    public static String GetAns(Player player, String job, String kind) {
        LazyOptional<JobCapability> capability = JobCapabilityProvider.getPlayerData(player);
        if(!capability.isPresent()) {
            return "未知";
        }
        PlayerSaveData playerSaveData = capability.resolve().get();
        switch(kind) {
            case JobParameterArgument.LEVEL:
                return Integer.toString(playerSaveData.getLevel(job));
            case JobParameterArgument.EXPERIENCE:
                return Double.toString(playerSaveData.getExperience(job));
            case JobParameterArgument.COEFFICIENT:
                return Double.toString(playerSaveData.getCoefficient(job));
        }
        return "未知";
    }

    public static int SetRead(boolean a, Player player) {
        JobCapabilityProvider.getPlayerData(player).ifPresent(playerSaveData -> playerSaveData.setReadGainExperience(a));
        return 0;
    }

    public static int SetRead(boolean a, CommandSourceStack context) {
        if(context.getEntity() instanceof ServerPlayer) {
            return SetRead(a, (ServerPlayer) context.getEntity());
        }
        return 0;
    }

    public static int GetRead(CommandSourceStack context) {
        if(context.getEntity() instanceof ServerPlayer serverplayer) {
            JobCapabilityProvider.getPlayerData(serverplayer).ifPresent(playerSaveData -> {
                serverplayer.sendMessage((new TranslatableComponent("jobsystem.commands.readgainexperience", new TranslatableComponent(String.valueOf(playerSaveData.isReadGainExperience())).withStyle(new ChatFormatting[] {ChatFormatting.GOLD}))), serverplayer.getUUID());
            });
        }
        return 0;
    }
}
